﻿using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.Extensions.Logging;

namespace LeoGemini.Service.Infrastructure.Handler.Filter
{
    public class ApiResponseFilter : ActionFilterAttribute
    {
        private readonly ILogger<ApiResponseFilter> _logger;

        public ApiResponseFilter(
            ILogger<ApiResponseFilter> logger)
        {
            _logger = logger;
        }
        
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            // _logger.LogInformation(((ObjectResult)context.Result).Value.ToString());

            if (context.ActionDescriptor is ControllerActionDescriptor descriptor)
            {
                var attributes = descriptor.EndpointMetadata;
                
                if (attributes.Any(attr => attr is ApiIgnoreAttribute)) return;

                var httpStatusCode = attributes.FirstOrDefault(attr => attr is HttpMethodAttribute) switch
                {
                    HttpDeleteAttribute => 204,
                    HttpPostAttribute => 201,
                    HttpGetAttribute => 200,
                    HttpPutAttribute => 200,
                    _ => 200
                };

                ApiResultAttribute apiResult = (ApiResultAttribute) attributes.FirstOrDefault(attr => attr is ApiResultAttribute);

                if (apiResult == null)
                {
                    apiResult = new ApiResultAttribute(httpStatusCode);
                }

                if (httpStatusCode != 204)
                {
                    context.Result = new JsonResult(
                        context.Result is ObjectResult result ? new
                        {
                            Code = apiResult.Code,
                            Message = apiResult.Message,
                            Data = result.Value
                        } : new
                        {
                            Code = apiResult.Code,
                            Message = apiResult.Message
                        }
                    );
                    ((JsonResult) context.Result).StatusCode = apiResult.StatusCode;
                }
                else
                {
                    context.Result = new NoContentResult();
                }
            }
        }
    }

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
    public class ApiIgnoreAttribute : Attribute
    {
        
    }

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
    public class ApiResultAttribute : Attribute
    {
        public int Code { get; private set; }
        
        public string Message { get; private set; }
        
        public int StatusCode { get; private set; }

        public ApiResultAttribute(int statusCode = 200, string message = "请求成功", int code = -1)
        {
            Message = message;
            StatusCode = statusCode;
            Code = code == -1 ? statusCode : code;
        }
    }
}